package org.cbioportal.legacy.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.cbioportal.legacy.model.GenesetMolecularAlteration;
import org.cbioportal.legacy.model.GenesetMolecularData;
import org.cbioportal.legacy.model.MolecularProfile;
import org.cbioportal.legacy.model.MolecularProfileSamples;
import org.cbioportal.legacy.model.Sample;
import org.cbioportal.legacy.persistence.MolecularDataRepository;
import org.cbioportal.legacy.service.MolecularProfileService;
import org.cbioportal.legacy.service.SampleService;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class GenesetDataServiceImplTest extends BaseServiceImplTest {

  @InjectMocks private GenesetDataServiceImpl genesetDataService;

  @Mock private MolecularDataRepository geneticDataRepository;
  @Mock private SampleService sampleService;
  @Mock private MolecularProfileService geneticProfileService;

  /**
   * This is executed n times, for each of the n test methods below:
   *
   * @throws Exception
   * @throws DaoException
   */
  @Before
  public void setUp() throws Exception {

    MolecularProfileSamples molecularProfileSamples = new MolecularProfileSamples();
    molecularProfileSamples.setMolecularProfileId(MOLECULAR_PROFILE_ID);
    molecularProfileSamples.setCommaSeparatedSampleIds("1,2,");

    // stub for samples
    Mockito.when(
            geneticDataRepository.getCommaSeparatedSampleIdsOfMolecularProfile(
                MOLECULAR_PROFILE_ID))
        .thenReturn(molecularProfileSamples);

    List<Sample> sampleList1 = new ArrayList<>();
    Sample sample = new Sample();
    sample.setInternalId(1);
    sample.setStableId(SAMPLE_ID1);
    sampleList1.add(sample);
    Mockito.when(
            sampleService.fetchSamples(Arrays.asList(STUDY_ID), Arrays.asList(SAMPLE_ID1), "ID"))
        .thenReturn(sampleList1);
    List<Sample> sampleListAll = new ArrayList<>(sampleList1);
    sample = new Sample();
    sample.setInternalId(2);
    sample.setStableId(SAMPLE_ID2);
    sampleListAll.add(sample);
    Mockito.when(
            sampleService.fetchSamples(
                Arrays.asList(STUDY_ID, STUDY_ID), Arrays.asList(SAMPLE_ID1, SAMPLE_ID2), "ID"))
        .thenReturn(sampleListAll);

    // stub for genetic profile
    MolecularProfile geneticProfile = new MolecularProfile();
    geneticProfile.setCancerStudyIdentifier(STUDY_ID);
    Mockito.when(geneticProfileService.getMolecularProfile(MOLECULAR_PROFILE_ID))
        .thenReturn(geneticProfile);

    // stub for repository data
    List<GenesetMolecularAlteration> genesetGeneticAlterationList = new ArrayList<>();
    GenesetMolecularAlteration genesetGeneticAlteration = new GenesetMolecularAlteration();
    genesetGeneticAlteration.setGenesetId(GENESET_ID1);
    genesetGeneticAlteration.setValues("0.2,0.499");
    genesetGeneticAlterationList.add(genesetGeneticAlteration);
    genesetGeneticAlteration = new GenesetMolecularAlteration();
    genesetGeneticAlteration.setGenesetId(GENESET_ID2);
    genesetGeneticAlteration.setValues("0.89,-0.509");
    genesetGeneticAlterationList.add(genesetGeneticAlteration);

    List<Integer> entrezGeneIds = new ArrayList<>();
    entrezGeneIds.add(ENTREZ_GENE_ID_1);
    Mockito.when(
            geneticDataRepository.getGenesetMolecularAlterations(
                MOLECULAR_PROFILE_ID, Arrays.asList(GENESET_ID1, GENESET_ID2), "SUMMARY"))
        .thenReturn(genesetGeneticAlterationList);
  }

  @Test
  public void fetchGenesetData() throws Exception {

    List<GenesetMolecularData> result =
        genesetDataService.fetchGenesetData(
            MOLECULAR_PROFILE_ID,
            Arrays.asList(SAMPLE_ID1, SAMPLE_ID2),
            Arrays.asList(GENESET_ID1, GENESET_ID2));

    // what we expect: 2 samples x 2 geneset items = 4 GenesetData items:
    // SAMPLE_1:
    //   geneset1 value: 0.2
    //   geneset2 value: 0.89
    // SAMPLE_2:
    //   geneset1 value: 0.499
    //   geneset2 value: -0.509
    Assert.assertEquals(4, result.size());
    GenesetMolecularData item1 = result.get(0);
    Assert.assertEquals(item1.getSampleId(), SAMPLE_ID1);
    Assert.assertEquals(item1.getGenesetId(), GENESET_ID1);
    Assert.assertEquals(item1.getValue(), "0.2");
    Assert.assertEquals(item1.getMolecularProfileId(), MOLECULAR_PROFILE_ID);
    GenesetMolecularData item2 = result.get(1);
    Assert.assertEquals(item2.getSampleId(), SAMPLE_ID1);
    Assert.assertEquals(item2.getGenesetId(), GENESET_ID2);
    Assert.assertEquals(item2.getValue(), "0.89");
    Assert.assertEquals(item2.getMolecularProfileId(), MOLECULAR_PROFILE_ID);
    GenesetMolecularData item4 = result.get(3);
    Assert.assertEquals(item4.getSampleId(), SAMPLE_ID2);
    Assert.assertEquals(item4.getGenesetId(), GENESET_ID2);
    Assert.assertEquals(item4.getValue(), "-0.509");
    Assert.assertEquals(item4.getMolecularProfileId(), MOLECULAR_PROFILE_ID);

    // check when selecting only 1 sample:
    result =
        genesetDataService.fetchGenesetData(
            MOLECULAR_PROFILE_ID,
            Arrays.asList(SAMPLE_ID1),
            Arrays.asList(GENESET_ID1, GENESET_ID2));
    Assert.assertEquals(2, result.size());
    item1 = result.get(0);
    Assert.assertEquals(item1.getSampleId(), SAMPLE_ID1);
    Assert.assertEquals(item1.getGenesetId(), GENESET_ID1);
    Assert.assertEquals(item1.getValue(), "0.2");
    Assert.assertEquals(item1.getMolecularProfileId(), MOLECULAR_PROFILE_ID);
  }
}
